package view.controller;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
import logic.FileSystem;
import logic.MyFile;
import logic.RespBean;
import lombok.SneakyThrows;
import view.GUI;

import view.WriteWindow;
import view.newFileWindow;
import view.newFolderWindow;

import java.io.IOException;
import java.net.URL;
import java.util.*;

public class DiskController implements Initializable {


    public DiskController() {

    }

    private Stage stage;
    private FileSystem fileSystem;

    @FXML
    private VBox vbox;

    @FXML
    private HBox hb1;
    @FXML
    private HBox hb2;
    @FXML
    private HBox hb3;
    @FXML
    private HBox hb4;
    @FXML
    private HBox hb5;

    private HBox[] hBoxes;

    @FXML
    private MenuItem help;

    @FXML
    private AnchorPane mainpane;

    @FXML
    private Button bu_close;

    @FXML
    private Button bu_min;

    @FXML
    private Button bu_max;

    @FXML
    private MenuBar menubar;

    @FXML
    private TreeView<MyFile> tv;

    @FXML
    private Group bu_group;

    @FXML
    private TextField path;

    @FXML
    private AnchorPane bu_an;

    @FXML
    private BorderPane main;

    @FXML
    private GridPane grid;

    @FXML
    private AnchorPane dragarea;

    @FXML
    private Button upBtn;

    public Map<Button, MyFile> map;

    private double xOffset = 0;
    private double yOffset = 0;

    private ContextMenu cm;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        hBoxes = new HBox[]{hb1, hb2, hb3, hb4, hb5};

        fileSystem = FileSystem.getInstance();
        map = new HashMap<>();
        initTreeView();//生成左边目录
        intializeRight();

        upBtn.setDisable(true);
        upBtn.setOnMouseClicked(e -> {
            fileSystem.parent = fileSystem.parent.getParent();
            intializeRight();
            if (fileSystem.parent == fileSystem.root) upBtn.setDisable(true);
        });

        dragarea.setOnMouseDragged(event -> {
            event.consume();
            Stage stage = getStage();
            this.stage.setX(event.getScreenX() - xOffset);
            this.stage.setY(event.getScreenY() - yOffset);
        });
        dragarea.setOnMousePressed(event -> {
            event.consume();
            xOffset = event.getSceneX();
            yOffset = event.getSceneY();
        });

        cm = new ContextMenu();

        vbox.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {
                if (e.getButton() == MouseButton.SECONDARY) {
                    if (cm.getItems().size() == 0) {
                        MenuItem newFile = new MenuItem();
                        MenuItem newFolder = new MenuItem();
                        newFile.setText("新建文件");
                        newFolder.setText("新建文件夹");
                        newFile.setOnAction(new EventHandler<ActionEvent>() {//item1的单击事件
                            @Override
                            public void handle(ActionEvent event) {
                                //System.out.println("new file");
                                // 新建文件
                                newFile();
                            }
                        });

                        newFolder.setOnAction(new EventHandler<ActionEvent>() {//item1的单击事件
                            @Override
                            public void handle(ActionEvent event) {
                                //System.out.println("new folder");
                                newFolder();
                            }
                        });

                        cm.getItems().addAll(newFile, newFolder);
                        cm.show(vbox, e.getScreenX(), e.getScreenY());
                    } else {
                        cm.show(vbox, e.getScreenX(), e.getScreenY());
                    }
                } else if (e.getButton() == MouseButton.PRIMARY) {
                    if (cm.isShowing()) cm.hide();
                }
            }
        });

        path.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.ENTER) {
                if (!path.getText().equals(fileSystem.parent.getPath())) {
                    MyFile file = fileSystem.fileMap.getOrDefault(path.getText(), null);
                    if (file == null) {
                        Alert alert = new Alert(Alert.AlertType.ERROR);
                        alert.setContentText("未找到该文件/目录");
                        alert.show();
                    } else {
                        if (file.isDirectory()) {
                            upBtn.setDisable(false);
                            fileSystem.openDirectory(file);
                            // 右边刷新一下parent
                            intializeRight();
                            if (fileSystem.parent == fileSystem.root) upBtn.setDisable(true);
                        } else {
                            ControllerTool tool = new ControllerTool("WriteWindow.fxml");
                            Parent window = null;
                            try {
                                window = tool.getParent();
                            } catch (IOException ioException) {
                                ioException.printStackTrace();
                            }
                            WriteWindowController controller = (WriteWindowController) tool.getController();
                            WriteWindow.display(window, controller, file);
                        }
                    }
                }
            }
        });
    }

    private void initTreeView() {
        tv.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @SneakyThrows
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (mouseEvent.getClickCount() == 2) {
                    TreeItem<MyFile> selectedItem = tv.getSelectionModel().getSelectedItem();
                    MyFile file = (selectedItem.getValue());
                    if (file.isDirectory()) {
                        upBtn.setDisable(false);
                        selectedItem.setExpanded(true);
                        fileSystem.openDirectory(file);
                        // 右边刷新一下parent
                        intializeRight();
                        if (fileSystem.parent == fileSystem.root) upBtn.setDisable(true);
                    } else {
                        ControllerTool tool = new ControllerTool("WriteWindow.fxml");
                        Parent window = tool.getParent();
                        WriteWindowController controller = (WriteWindowController) tool.getController();
                        WriteWindow.display(window, controller, file);
                    }
                }
            }
        });
        flushLeft();
    }

    public void flushLeft() {
        TreeItem<MyFile> root = initTree(fileSystem.root);
        root.setExpanded(true);
        tv.setRoot(root);
    }

    public TreeItem<MyFile> initTree(MyFile file) {
        TreeItem<MyFile> item = new TreeItem<>(file);
        if (file.getChildList() != null) {
            for (MyFile child : file.getChildList()) {
                TreeItem<MyFile> i = initTree(child);
                item.getChildren().add(i);
            }
        }
        if (!item.isLeaf()) item.setExpanded(true);
        return item;
    }

    public void addRClick(Button button) {

        button.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @SneakyThrows
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (mouseEvent.getClickCount() == 2) {
                    MyFile file = map.get(button);
                    if (file.isDirectory()) {
                        upBtn.setDisable(false);
                        fileSystem.openDirectory(file);
                        // 右边刷新一下parent
                        intializeRight();
                    } else {
                        ControllerTool tool = new ControllerTool("WriteWindow.fxml");
                        Parent window = tool.getParent();
                        WriteWindowController controller = (WriteWindowController) tool.getController();
                        WriteWindow.display(window, controller, file);
                    }
                }
            }
        });
        
        button.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (cm.isShowing()) cm.hide();

                if (mouseEvent.getButton() == MouseButton.SECONDARY) {
                    ContextMenu contextMenu = new ContextMenu();
                    MenuItem menuItem1 = new MenuItem();
                    MenuItem menuItem2 = new MenuItem();
                    MenuItem menuItem3 = new MenuItem();
                    MenuItem menuItem4 = new MenuItem();
                    menuItem1.setText("打开");
                    menuItem1.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent actionEvent) {
                            MyFile file = map.get(button);
                            if (file.isDirectory()) {
                                upBtn.setDisable(false);
                                fileSystem.openDirectory(file);
                                //todo: 右边刷新一下parent
                                intializeRight();
                            } else {
                                ControllerTool tool = new ControllerTool("WriteWindow.fxml");
                                Parent window = null;
                                try {
                                    window = tool.getParent();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                                WriteWindowController controller = (WriteWindowController) tool.getController();
                                WriteWindow.display(window, controller, file);
                            }
                        }
                    });
                    menuItem2.setText("修改");
                    menuItem2.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent actionEvent) {
                            if (map.get(button).isDirectory()) modifyFolder(button);
                            else modifyFile(button);
                        }
                    });
                    menuItem3.setText("删除");
                    menuItem3.setOnAction(e -> {
                        MyFile file = map.get(button);
                        RespBean respBean = null;
                        if (file.isDirectory()) {
                            respBean = fileSystem.deleteDirectory(file);
                        } else {
                            respBean = fileSystem.deleteFile(file);
                        }
                        if (respBean.isRes()) {
                            map.remove(button);
                            flushLeft();
                            flush();
                        } else {
                            Alert alert = new Alert(Alert.AlertType.ERROR);
                            alert.setTitle("删除失败");
                            alert.setContentText(respBean.getMessage());
                            alert.show();
                        }
                    });
                    menuItem4.setText("属性");
                    menuItem4.setOnAction(e -> {
                        MyFile file = map.get(button);
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("文件信息");
                        String info = "文件路径：" + file.getPath()
                                + "\n文件类型：" + (file.isDirectory() ? "文件夹" : "文件")
                                + "\n文件属性：" + (file.getAttr()%2==1 ? "只读" : "读写")
                                + "\n文件大小：" + file.getSize()
                                + "\n父目录记录坐标：（" + file.getCoordinate().getKey() + "：" + file.getCoordinate().getValue() + "）"
                                + "\n文件信息起始盘块号：" + file.getInitBlockId();
                        alert.setContentText(info);
                        alert.show();
                    });
                    contextMenu.getItems().add(menuItem1);
                    contextMenu.getItems().add(menuItem2);
                    contextMenu.getItems().add(menuItem3);
                    contextMenu.getItems().add(menuItem4);
                    button.setContextMenu(contextMenu);
                }
            }

        });
    }

    public void intializeRight() {
        map = new HashMap<>();
        for (MyFile myFile : fileSystem.getParent().getChildList()) {
            Button bu = new Button();
            ImageView img = new ImageView(newFileWindow.class.getClassLoader().getResource(myFile.isDirectory() ? "Folder.jpg" : "File.jpg").toString());
            img.setFitHeight(70);
            img.setFitWidth(70);
            bu.setPrefSize(70, 80);
            addRClick(bu);
            VBox vBox = new VBox();
            vBox.setAlignment(Pos.CENTER);
            vBox.getChildren().add(img);
            vBox.getChildren().add(new Label(myFile.getName() + (myFile.isDirectory() ? "" : ("." + myFile.getType()))));
            bu.setGraphic(vBox);
            map.put(bu, myFile);
        }
        flush();
    }

    public AnchorPane getMainpane() {
        return mainpane;
    }

    public void modifyFolder(Button button) {
        try {
            ControllerTool controllerTool = new ControllerTool("newFolderWindow.fxml");
            newFolderWindow.display2(controllerTool.getParent(), (NewFolderWindowController) controllerTool.getController(), this, button);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void modifyFile(Button button) {
        try {
            ControllerTool controllerTool = new ControllerTool("newFileWindow.fxml");
            newFileWindow.display2(controllerTool.getParent(), (NewFileWindowController) controllerTool.getController(), this, button);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void newFile() {
        try {
            ControllerTool controllerTool = new ControllerTool("newFileWindow.fxml");
            newFileWindow.display(controllerTool.getParent(), (NewFileWindowController) controllerTool.getController(), this);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void flush() {
        List<Button> list = new ArrayList<Button>(map.keySet());
        Collections.sort(list, (b1, b2) -> {
            MyFile f1 = map.get(b1);
            MyFile f2 = map.get(b2);
            if (f1.isDirectory() && !f2.isDirectory())
                return -1;
            if (!f1.isDirectory() && f2.isDirectory())
                return 1;
            return f1.getName().compareTo(f2.getName());
        });
        for (Button button : list) {
            //System.out.println(map.get(button).getName());
        }
        Iterator<Button> iterator = list.iterator();
        for (int i = 0; i < 5; i++) {
            HBox hBox = hBoxes[i];
            //System.out.println(hBox.getChildren().size());
            int size = hBox.getChildren().size();
            for (int k = 0; k < size; k++) {
                hBox.getChildren().remove(0);
            }
            //System.out.println("clear");
            //System.out.println(list);
            for (int j = 0; j < 5; j++) {
                //if(hBox.getChildren().size() < j )hBox.getChildren().remove(j);
                if (iterator.hasNext()) {
                    hBox.getChildren().add(iterator.next());
                }
            }
        }
        path.setText(fileSystem.parent.getPath());
        flushLeft();
    }

    public void newFolder() {
        try {
            ControllerTool controllerTool = new ControllerTool("newFolderWindow.fxml");
            newFolderWindow.display(controllerTool.getParent(), (NewFolderWindowController) controllerTool.getController(), this);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void close() {
        Stage stage = (Stage) main.getScene().getWindow();
        stage.close();
    }


    public void min() {
        Stage stage = (Stage) main.getScene().getWindow();
        stage.setIconified(true);
    }

    double x = 0;
    double y = 0;


    public void help() {
        //弹出窗口，alert类型即可
        //帮助页面，类似使用说明
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("帮助");
        String info = "1. 双击左侧目录树可打开相应的文件/目录"
                + "\n2. 在右侧搜索框中输入文件/目录路径可以查找到相应文件/目录"
                + "\n\t如： Root/home/test1.txt"
                + "\n3. 当文件的只读和可写属性都被勾选时，属性为只读"
                + "\n4. 当文件的只读和可写属性都未勾选时，属性为读写";
        alert.setContentText(info);
        alert.show();
    }

    private Stage getStage() {
        if (stage == null) {
            stage = (Stage) main.getScene().getWindow();
        }
        return stage;
    }
}